﻿using System;
using System.Diagnostics;
using YKXiangQi.Common;
using YKXiangQi.EventHandlers;
using YKXiangQi.Models;

namespace YKXiangQi.Adapters
{
    public class UciEngineAdapter: EngineAdapter
    {
        public override void InitEngine()
        {
            SendCommand(Constant.Commands.Uci);
            if (!_manualResetEvent.WaitOne(Constant.WaitTimeout))
            {
                Stop();
                OnEngineOutputReceived(new EngineOutputReceivedEventArgs() {Data = "Cannot start engine!"});
                return;
            }

            SendCommand(Constant.Commands.IsReady);
        }

        public override void NewGame()
        {
            SendCommand(Constant.Commands.UciNewGame);
        }

        protected override void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (string.IsNullOrEmpty(e.Data))
                return;

            switch (e.Data)
            {
                case Constant.FeedBacks.UciOk:
                case Constant.FeedBacks.ReadyOk:
                    {
                        _manualResetEvent.Set();
                        break;
                    }
            }

            if (e.Data.StartsWith(Constant.FeedBacks.BestMove)
                && IsLastCommandStopThinking)
            {
                lock (obj)
                {
                    IsLastCommandStopThinking = false;
                }
                return;//don't send 'bestmove' feedback to GUI
            }

            OnEngineOutputReceived(new EngineOutputReceivedEventArgs() {Data = e.Data});
        }

        public override void SetPosition(string fen)
        {
            SendCommand(Constant.Commands.Fen, fen);
            SendCommand(Constant.Commands.Position, fen);
        }

        public override void Go()
        {
            Go(null); //don't use timer
        }

        public override void Go(TimerSettings timerSettings)
        {
            lock (obj)
            {
                IsLastCommandStopThinking = false;
            }

            var goCommand = Constant.Commands.Go;

            if (timerSettings != null) //use timer??
            {
                goCommand += " " + string.Format(Constant.Commands.Parameters.WTime, timerSettings.RedTotalTime*1000);
                goCommand += " " + string.Format(Constant.Commands.Parameters.BTime, timerSettings.BlackTotalTime*1000);

                if (timerSettings.IsIncreaseTime)
                {
                    goCommand += " " + string.Format(Constant.Commands.Parameters.WInc, timerSettings.IncreasedTimeAmount*1000);
                    goCommand += " " + string.Format(Constant.Commands.Parameters.BInc, timerSettings.IncreasedTimeAmount*1000);
                }
            }
            else
            {
                if (Settings.DepthLimit <= 0)
                    goCommand += " " + string.Format(Constant.Commands.Parameters.Depth, Constant.Commands.Parameters.Infinite);
                else
                    goCommand += " " + string.Format(Constant.Commands.Parameters.Depth, Settings.DepthLimit);

                if (Settings.TimeLimit > 0)
                    goCommand += " " + string.Format(Constant.Commands.Parameters.MoveTime, Settings.TimeLimit * 1000);
            }

            SendCommand(goCommand);
        }

        public override void Analyze()
        {
            lock (obj)
            {
                IsLastCommandStopThinking = false;
            }

            var goCommand = Constant.Commands.Go;
            goCommand += " " + Constant.Commands.Parameters.Infinite;

            SendCommand(goCommand);
        }

        public override void Stop()
        {
            SendCommand(Constant.Commands.Stop);
        }

        public override void StopThinking()
        {
            lock (obj)
            {
                IsLastCommandStopThinking = true;    
            }
            SendCommand(Constant.Commands.Stop);
        }
    }
}
